package com.aiden.app.common.http.cookie;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import com.aiden.app.common.http.config.HttpGlobalConfig;
import com.aiden.app.common.util.HexUtil;
import com.aiden.app.common.util.LogUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.Cookie;
import okhttp3.HttpUrl;

/**
 *
 * cookie操作工具
 * @author yanggeng
 * @date 2018/12/17 下午4:52
 */
public class CookieShop {

    private static final String LOG_TAG = CookieShop.class.getSimpleName();
    private SharedPreferences cookiesPrefs;
    private Map<String, ConcurrentHashMap<String, Cookie>> cookies;

    public CookieShop(Context context) {
        cookiesPrefs = context.getSharedPreferences(HttpGlobalConfig.PREFS_COOKIE, Context.MODE_PRIVATE);
        cookies = new HashMap<>();
        Map<String, ?> prefsMap = cookiesPrefs.getAll();
        for (Map.Entry<String, ?> pref : prefsMap.entrySet()) {
            String[] cookieNames = TextUtils.split((String) pref.getValue(), ",");
            for (String cookieName : cookieNames) {
                String encodeCookie = cookiesPrefs.getString(cookieName, null);
                if (encodeCookie != null) {
                    Cookie decodeCookie = decodeCookie(encodeCookie);
                    if (decodeCookie != null) {
                        if (!cookies.containsKey(pref.getKey())) {
                            cookies.put(pref.getKey(), new ConcurrentHashMap<String, Cookie>());
                        }
                        cookies.get(pref.getKey()).put(cookieName, decodeCookie);
                    }
                }
            }
        }
    }

    private String getCookieToken(Cookie cookie) {
        return cookie.name() + "@" + cookie.domain();
    }

    public void add(HttpUrl url, Cookie cookie) {
        String name = getCookieToken(cookie);
        boolean hasExpired = cookie.persistent() && ((cookie.expiresAt() - System.currentTimeMillis()) / 1000 < 0);
        if (hasExpired) {
            if (cookies.containsKey(url.host())) {
                cookies.put(url.host(), new ConcurrentHashMap<>());
            }
            cookies.get(url.host()).put(name, cookie);
        } else {
            if (cookies.containsKey(url.host())) {
                cookies.get(url.host()).remove(name);
            }
        }
        SharedPreferences.Editor editor = cookiesPrefs.edit();
        if (cookies.get(url.host()) != null) {
            editor.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));
        }
        editor.putString(name, encodeCookie(new OkHttpCookie(cookie)));
        LogUtils.INSTANCE.d(LOG_TAG, "-----------add cookie------------");
    }

    public List<Cookie> get(HttpUrl url) {
        List<Cookie> cookieList = new ArrayList<>();
        if (cookies.containsKey(url.host())) {
            cookieList.addAll(cookies.get(url.host()).values());
        }
        return cookieList;
    }

    public boolean removeAll() {
        SharedPreferences.Editor editor = cookiesPrefs.edit();
        editor.clear();
        editor.apply();
        cookies.clear();
        return true;
    }

    public List<Cookie> getCookies() {
        List<Cookie> cookieList = new ArrayList<>();
        for (String key : cookies.keySet()) {
            cookieList.addAll(cookies.get(key).values());
        }
        return cookieList;
    }

    public boolean remove(HttpUrl url, Cookie cookie) {
        String name = getCookieToken(cookie);
        if (cookies.containsKey(url.host()) && cookies.get(url.host()).containsKey(name)) {
            cookies.get(url.host()).remove(name);
            SharedPreferences.Editor editor = cookiesPrefs.edit();
            if (cookiesPrefs.contains(name)) {
                editor.remove(name);
            }
            editor.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));
            editor.apply();
            return true;
        }
        return false;
    }

    private String encodeCookie(OkHttpCookie cookie) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(cookie);
        } catch (IOException e) {
            LogUtils.INSTANCE.e(LOG_TAG, e.getMessage());
            return null;
        }
        return HexUtil.INSTANCE.encodeHexStr(bos.toByteArray());
    }

    private Cookie decodeCookie(String cookieString) {
        byte[] bytes = HexUtil.INSTANCE.decodeHex(cookieString.toCharArray());
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Cookie cookie = null;
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            cookie = ((OkHttpCookie) objectInputStream.readObject()).getCookies();
        } catch (IOException | ClassNotFoundException e) {
            LogUtils.INSTANCE.e(LOG_TAG, e.getMessage());
        }
        return cookie;
    }
}
